package com.example.leetcode.juc;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

//class TrafficLight {
//
//    private final Semaphore semaphore = new Semaphore(1);
//    // road A 是否是绿灯
//    // true 表示是绿灯
//    // 开始时，A 路上的绿灯亮起，B 路上的红灯亮起。
//    private boolean road1GreenOn = true;
//
//    public TrafficLight() {
//
//    }
//
//    /**
//     * @param carId     ID of the car
//     * @param roadId    ID of the road the car travels on. Can be 1 (road A) or 2 (road B)
//     * @param direction Direction of the car
//     * @param turnGreen Use turnGreen.run() to turn light to green on current road
//     * @param crossCar  Use crossCar.run() to make car cross the intersection
//     */
//    public void carArrived(int carId, int roadId, int direction, Runnable turnGreen, Runnable crossCar) {
//
//        try {
//            // 获取信号量
//            semaphore.acquire();
////            System.out.println(Thread.currentThread().getName() + String.format(" 车辆 %d 允许通过红绿灯路口", carId));
//
//            if (roadId == 1 && road1GreenOn == false) {
//                // 开启A路的绿灯
//                turnGreen.run();
//                // A路的绿灯开启
//                road1GreenOn = true;
//            } else if (roadId == 2 && road1GreenOn == true) {
//                // 开启B路的绿灯
//                turnGreen.run();
//                // A路的绿灯关闭
//                road1GreenOn = false;
//            }
//            // 车辆通过
//            crossCar.run();
//            // 释放信号量
//            semaphore.release();
//        } catch (Exception e) {
//
//        }
//
//    }
//}

class TrafficLight {

    // a路开始时绿灯
    volatile int a = 0;
    // b路开始时红灯
    volatile int b = 1;
    ReentrantLock lock = new ReentrantLock();

    public TrafficLight() {

    }

    public void carArrived(
            int carId,           // ID of the car
            int roadId,          // ID of the road the car travels on. Can be 1 (road A) or 2 (road B)
            int direction,       // Direction of the car
            Runnable turnGreen,  // Use turnGreen.run() to turn light to green on current road
            Runnable crossCar    // Use crossCar.run() to make car cross the intersection
    ) {
        lock.lock();
        if ((direction == 1 || direction == 2) && a == 1) {
            // 如果a路红灯，调整为绿灯
            turnGreen.run();
            a = 0;
            b = 1;
        } else if ((direction == 3 || direction == 4) && b == 1) {
            // 如果b路红灯，调整为绿灯
            turnGreen.run();
            b = 0;
            a = 1;
        }
        crossCar.run();
        lock.unlock();
    }
}


public class leetcode1279 {
    public static void main(String[] args) {

        // 输入: cars = [1,2,3,4,5], directions = [2,4,3,3,1], arrivalTimes = [10,20,30,40,40]

        int[] cars = {1, 3, 5, 2, 4};
        int[] directions = {2, 1, 2, 4, 3};
        int[] arrivalTimes = {10, 20, 30, 40, 50};

//        int[] cars = {1, 2, 3, 4, 5};
//        int[] directions = {2, 4, 3, 3, 1};
//        int[] arrivalTimes = {1, 4, 4, 4, 4};


        TrafficLight trafficLight = new TrafficLight();

        // 如何写测试方法

        for (int i = 0; i < cars.length; i++) {
            if (i == 0) {
                sleepsometime(arrivalTimes[0]);
            } else {
                sleepsometime(arrivalTimes[i] - arrivalTimes[i - 1]);
            }
            int carId = cars[i];
            int direction = directions[i];
            int roadId = getRoadIdByDir(direction);
            String convertRoadId = convertRoadId(roadId);

            Runnable turnGreen = () -> System.out.printf("Traffic Light On Road %s Is Green\n", convertRoadId);
            Runnable crossCar = () -> System.out.printf("Car %s Has Passed Road %s In Direction %s\n", carId, convertRoadId, direction);

//            System.out.println(Thread.currentThread().getName() + String.format("=> 第 %d 辆车到达红绿灯路口", i + 1));
            // 可以使用两个线程池模拟两条路
            int finalI = i + 1;
            new Thread(() -> {
                sleepsometime(new Random().nextInt(2) + 1);
                trafficLight.carArrived(carId, roadId, direction, turnGreen, crossCar);
//                System.out.println(Thread.currentThread().getName() + String.format("=> 第 %d 辆车通过红绿灯路口", finalI));
            }, String.valueOf(i + 1)).start();

        }


        // 输出: [
        // "Car 1 Has Passed Road A In Direction 2",    // A 路上的红绿灯为绿色，1 号车可通过路口。
        // "Traffic Light On Road B Is Green",          // 2 号车在 B 路请求绿灯。
        // "Car 2 Has Passed Road B In Direction 4",    // B 路上的绿灯现已亮起，2 号车通过路口。
        // "Car 3 Has Passed Road B In Direction 3",    // B 路上的绿灯现已亮起，3 号车通过路口。
        // "Traffic Light On Road A Is Green",          // 5 号车在 A 路请求绿灯。
        // "Car 5 Has Passed Road A In Direction 1",    // A 路上的绿灯现已亮起，5 号车通过路口。
        // "Traffic Light On Road B Is Green",          // 4 号车在 B 路请求绿灯。4 号车在路口等灯，直到 5 号车通过路口，B 路的绿灯亮起。
        // "Car 4 Has Passed Road B In Direction 3"     // B 路上的绿灯现已亮起，4 号车通过路口。
        // ]
        // 解释: 这是一个无死锁的方案。注意，在 A 路上的绿灯亮起、5 号车通过前让 4 号车通过，也是一个正确且可被接受的方案。


    }

    private static String convertRoadId(int roadId) {
        String str = "";
        if (roadId == 1) {
            str = "A";
        } else if (roadId == 2) {
            str = "B";
        }
        return str;
    }

    private static void sleepsometime(int time) {
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static int getRoadIdByDir(int direction) {
        if (direction == 1 || direction == 2) {
            return 1;
        } else if (direction == 3 || direction == 4) {
            return 2;
        }
        return 0;
    }
}
